﻿
Imports std
Imports xmlctrl
Imports xhtmlctrl
Imports webctrl
Imports wfileis.data

Public Class view
    Inherits cacheControlProcessor

    Public Const _pathidentity As String = "/view"
    Public Const resultPerPage As Int16 = 10
    Public Const paginationLinkCount As Int16 = 10
    Public Const viewdivId As String = "vw_v"
    Public Const ajaxfailedTextVar As String = "vaft"

    Protected Overrides Function normalretiredticks() As Long
        Return secondsToTicks(10)
    End Function

    Public Overrides Function pathidentity() As String
        Return _pathidentity
    End Function

    Public Shared Function baseurl() As String
        Return strmid(_pathidentity, strlen(network.pathSeperator))
    End Function

    Public Shared Function generateViewlink(ByVal context As httpContext, ByVal key As String, _
                                            Optional ByVal ignoreText As Boolean = True) As String
        assert(Not context Is Nothing, "context is nothing.")

        Dim rtn As String = Nothing
        rtn = generateLink(context, baseurl(), query.key, ignoreText)
        rtn = urlUtils.appendQuery(rtn, query.key, key)

        Return rtn
    End Function

    Public Shared Function generateViewlink(ByVal key As String, _
                                            Optional ByVal ignoreText As Boolean = True) As String
        Return generateViewlink(httpServer2.currentContext(), key, ignoreText)
    End Function

    Private Shared Function failedToGetResponseString(ByVal context As httpContext) As String
        Return context.string(stringId.VIEW_FAILREADINFO)
    End Function

    Private Shared Function failedToGetResponseString() As String
        Return failedToGetResponseString(httpServer2.currentContext())
    End Function

    Private Shared Sub registerAjax(ByVal page As xhtmlpage, ByVal context As httpContext)
        webctrl.var.invoke(page.inlineScript(), ajaxfailedTextVar, "'" + failedToGetResponseString() + "'")
        ajaxresponse.register(page.inlineScript())
    End Sub

    Private Shared Function invokeAjax(ByVal url As String) As String
        Return ajaxresponse.invoke(CType(Nothing, inlineScript), "'" + url + "'", _
                                   failedToGetResponse:=ajaxfailedTextVar)
    End Function

    Private Shared Function paginationInvoke(ByVal url As String) As String
        Return changeInnerHtmlById.invoke(Nothing, "'" + viewdivId + "'", invokeAjax(url))
    End Function

    'for serverlet only
    Public Shared Function generateViewlink(ByVal key As String, ByVal first As Int64) As a
        Dim url As String = Nothing
        url = baseurl()

        url = urlUtils.appendQuery(url, query.key, key)
        url = urlUtils.appendQuery(url, query.first, first)
        url = urlUtils.appendQuery(url, query.nopage, "1")

        Dim rtn As emptyA = Nothing
        rtn = New emptyA()
        rtn.onclick = paginationInvoke(url)
        Return rtn
    End Function

    Public Shared Function generateLastViewlink(ByVal key As String) As String
        Dim url As String = Nothing
        url = baseurl()

        url = urlUtils.appendQuery(url, query.key + _
                                        network.argumentNameValueSeparator + key)
        url = urlUtils.appendQuery(url, query.last, "1")
        url = urlUtils.appendQuery(url, query.nopage, "true")

        Return paginationInvoke(url)
    End Function

    Private Function processNoKey(ByVal context As httpContext, ByRef control As xmlcontrol) As Boolean
        assert(Not context Is Nothing, "context is nothing.")
        assert(control Is Nothing, "control should be nothing.")

        Dim page As xhtmlpage = Nothing
        page = context.createControl(New xhtmlpage())
        page.title().text = context.string(stringId.VIEW_TITLE_NOKEY)

        page.body().addchild(header.generateInstance(page))

        Dim label As label = Nothing
        label = context.createControl(New label())
        label.text = context.string(stringId.VIEW_NOKEY)
        page.body().addchild(label)
        page.body().addchild(New br())

        Dim a As a = Nothing
        a = context.createControl(New a())
        a.text = context.string(stringId.AUTOGOBACKTOHOMEPAGE)
        a.href = network.thislevelPathMark
        page.body().addchild(a)

        Dim delayjump As delayJump = Nothing
        delayjump = context.createControl(New delayJump())
        delayjump.destination = a.href
        delayjump.delay = 10
        page.head().addchild(delayjump)

        control = page
        Return True
    End Function

    Private Function processKeyNoFound(ByVal context As httpContext, ByRef control As xmlcontrol, _
                                       ByVal key As String) As Boolean
        assert(Not context Is Nothing, "context is nothing.")
        assert(control Is Nothing, "control should be nothing.")

        Dim page As xhtmlpage = Nothing
        page = context.createControl(New xhtmlpage())
        page.title().text = context.string(stringId.VIEW_TITLE_KEYNOFOUND)

        page.body().addchild(header.generateInstance(page))

        Dim label As label = Nothing
        label = context.createControl(New label())
        label.text = context.string(stringId.VIEW_KEYNOFOUND) + character.blank + key
        page.body().addchild(label)
        page.body().addchild(context.createControl(New br()))

        addwriter(context, page, page.body(), False)

#If RETIRED Then
        Dim a As a = Nothing
        a = context.createControl(New a())
        a.text = context.string(stringId.VIEW_WIRTESOMETHINGTOKEY)
        a.href = urlUtils.appendQuery(homepage._pathidentity, homepage.keyQuery, key)
        page.body().addchild(a)
#End If

        control = page
        Return True
    End Function

    Private Function processKeyImpl(ByVal context As httpContext, ByVal root As xmlcontrol, _
                                    ByVal key As String, ByVal record As record, _
                                    Optional ByVal page As xhtmlpage = Nothing) As Boolean
        assert(Not context Is Nothing, "context is nothing.")
        assert(Not root Is Nothing, "root is nothing.")

        Dim first As Int64
        first = context.url().queryInt64(query.first)
        Dim existlast As Boolean
        existlast = context.url().queryBoolean(query.last)

        Dim v As vector(Of String) = Nothing
        'fully trust if record/list is valid, it should be able to convert to vector, so return false if failed.
        If list2vector(record, v) Then
            If sort(v.rawdata(), 0, v.size()) Then
                Dim pg As pagination = Nothing
                pg = context.createControl(New pagination())
                root.addchild(pg)

#If RETIRED Then
                Dim v2 As vector(Of String) = Nothing
                v2 = New vector(Of String)()
                For i = 1 To v.size() - 1
                    If Not isemptystring(v(i)) AndAlso Not strsame(v(i - 1), v(i), True) Then
                        v2.push_back(v(i))
                    End If
                Next
                'do not dedup, it's something wrong, should not be cared
#End If

                Dim h3 As h3 = Nothing
                h3 = context.createControl(New h3())
                h3.text = key
                root.addchild(h3)

                Dim info As info = Nothing
                info = New info()
                Dim last As Int64
                If existlast Then
#If RETIRED Then
                    first = v2.size() - resultPerPage
                    last = v2.size()
#End If
                    first = v.size() - resultPerPage
                    If first < 0 Then
                        first = 0
                    End If
                    last = v.size()
                Else
                    If first <= npos Then
                        first = 0
                    End If
                    last = first + resultPerPage
#If RETIRED Then
                    If last > v2.size() Then
                        last = v2.size()
                    End If
#End If
                    If last > v.size() Then
                        last = v.size()
                    End If
                End If
#If RETIRED Then
                pg.setData(key, first, v2.size())
#End If
                pg.setData(page, key, first, v.size())

                Dim i As Int64
#If RETIRED Then
                i = first
                While i < last
                    If Not isemptystring(v(i)) AndAlso (i = 0 OrElse Not strsame(v(i - 1), v(i), True)) Then
#End If
                For i = first To last - 1
                    Dim div As div = Nothing
                    div = context.createControl(New div())
                    div.class = "b"
                    colorfulControl.invoke(page, div)
                    root.addchild(div)

                    Dim ava As avatar = Nothing
                    ava = context.createControl(New avatar())
                    div.addchild(ava)

                    Dim h4 As h4 = Nothing
                    h4 = context.createControl(New h4())
                    div.addchild(h4)
                    If info.read(v(i)) Then
                        ava.setData(info)
                        Dim idshow As idshow = Nothing
                        idshow = context.createControl(New idshow())
                        idshow.setData(info)
                        h4.addchild(idshow)
                        Dim xmltext As xmltext = Nothing
                        xmltext = context.createControl(New xmltext())
                        xmltext.text = character.blank + context.string(stringId.VIEW_SAY)
                        h4.addchild(xmltext)
#If RETIRED Then
                        If Not isemptystring(info.id) Then
                            Dim a As a = Nothing
                            a = context.createControl(New a())
                            a.text = info.id
                            a.href = user.generateUserViewlink(context, info.id)
                            h4.addchild(a)

                            Dim xmltext As xmltext = Nothing
                            xmltext = context.createControl(New xmltext())
                            xmltext.text = character.blank + context.string(stringId.VIEW_SAY)
                            h4.addchild(xmltext)
                        Else
                            h4.text = context.string(stringId.INFO_NOID) + character.blank + _
                                      context.string(stringId.VIEW_SAY)
                        End If
                        h4.text = info.time + " - " + context.string(stringId.VIEW_INFOID) + info.id + _
                                  context.string(stringId.VIEW_INFOFROM) + info.from

                        Dim pre As pre = Nothing
                        pre = context.createControl(New autowrappre(page))
                        pre.text = htmlUtils.escape(info.text)
                        div.addchild(pre)
#End If
                        Dim from As String = Nothing
                        'Const hideipstart As Byte = 4
                        Const hideipbits As Byte = 5
                        Dim ipbitsReplacer As String = New String(character.asterisk, hideipbits)
                        copy(from, info.from)
                        strrplc(from, Convert.ToInt64(rnd(0, strlen(from) - hideipbits, True)), ipbitsReplacer)
                        'strrplc(from, hideipstart, ipbitsReplacer)

                        Dim cite As cite = Nothing
                        cite = context.createControl(New cite())
                        cite.text = "-- " + info.time + " - " + context.string(stringId.VIEW_INFOFROM) + from
                        div.addchild(cite)

                        Dim pv As posterViewer = Nothing
                        pv = context.createControl(New posterViewer())
                        Dim ds As posterViewer.datasource = Nothing
                        ds = New posterViewer.datasource()
                        ds.page = page
                        ds.text = info.text
                        ds.isIEUserAgent = context.isIEUserAgent()
                        pv.setData(ds)
                        pv.class = "pv"
                        div.addchild(pv)
                    Else
                        raiseError("cannot read info " + v(i), errorHandle.errorType.warning)
                        h4.text = context.string(stringId.VIEW_FAILREADINFO)
                    End If
                Next
#If RETIRED Then
                    Else
                        last += 1
                    End If

                    i += 1
                End While
#End If

                pg = context.createControl(New pagination())
#If RETIRED Then
                pg.setData(key, first, count)
#End If
                pg.setData(page, key, first, v.size())
                root.addchild(pg)

                If Not page Is Nothing Then
                    addwriter(context, page, page.body(), False)
                    'though do not need to register them, as the page will certainly have these functions, 
                    'but it's safe to register them.
                    'in avoid to have an all async page
                    changeInnerHtmlById.register(page.inlineScript())
                    registerAjax(page, context)
                End If
#If RETIRED Then
                Dim a As a = Nothing
                a = context.createControl(New a())
                a.text = context.string(stringId.VIEW_WIRTESOMETHINGTOKEY)
                a.href = urlUtils.appendQuery(homepage._pathidentity, homepage.keyQuery, key)
                page.body().addchild(a)
#End If
            Else
                raiseError("cannot sort vector.", errorHandle.errorType.warning)
                Return False
            End If
            Return True
        Else
            raiseError("cannot convert list to vector.", errorHandle.errorType.warning)
            Return False
        End If
    End Function

    Private Function processKey(ByVal context As httpContext, ByRef control As xmlcontrol, _
                                ByVal key As String, ByVal record As record) As Boolean
        assert(Not context Is Nothing, "context is nothing.")
        assert(Not record Is Nothing, "record is nothing.")
        assert(control Is Nothing, "control should be nothing.")

        Dim nopage As Boolean
        nopage = context.url().queryExist(query.nopage)

        If nopage Then
            Dim root As container = Nothing
            root = context.createControl(New container())
            control = root
            Return processKeyImpl(context, root, key, record)
        Else
            Dim page As xhtmlpage = Nothing
            page = context.createControl(New xhtmlpage())
            page.addcsslink(cssrequest.generateCssfileLinkUrl("view.css"))
            page.title().text = key + context.string(stringId.VIEW_TITLE_RESULT)
            control = page

            page.body().addchild(header.generateInstance(page))

            Dim div As div = Nothing
            div = context.createControl(New div())
            div.id = viewdivId
            page.body().addchild(div)
            Return processKeyImpl(context, div, key, record, page)
        End If
    End Function

    Protected Overrides Function processImpl(ByVal context As httpContext, ByRef control As xmlcontrol) As Boolean
        assert(Not context Is Nothing, "context is nothing.")
        Dim key As String = Nothing
        key = context.url().query(query.key)
        If isemptystring(key) Then
            Return processNoKey(context, control)
        Else
            Dim record As record = Nothing
            record = New record()
            If Not record.read(key) Then
                Return processKeyNoFound(context, control, key)
            Else
                Return processKey(context, control, key, record)
            End If
        End If

        debugassert(False, "should cover all possibilities already.")
        Return False
    End Function
End Class
